package swing;

import java.util.ArrayList;

import slidingPuzzle.SlidingPuzzle;

//SlidePuzzleModel.java - Slide pieces to correct position.
//Fred Swartz, 2003-May-10

/////////////////////////////////////////// class SlidePuzzleModel
public class SlidePuzzleModel {
// private static final int puzzleSize = 3;
// private static final int puzzleSize = 3;
	private int puzzleSize;
 
 private Tile[][] _contents;  // All tiles.
 private Tile     _emptyTile; // The empty space.
 public Tile[][] getContents() {
	return _contents;
 }


 public void setContents(Tile[][] _contents) {
	this._contents = _contents;
 }

 
 
 //================================================= constructor
 public SlidePuzzleModel(int puzzleSize) {
	 this.puzzleSize = puzzleSize;
     _contents = new Tile[puzzleSize][puzzleSize];
     reset();               // Initialize and shuffle tiles.
 }//end constructor
 
 
 //===================================================== getFace
 // Return the string to display at given row, col.
 String getFace(int row, int col) {
     return _contents[row][col].getFace();
 }//end getFace
 
 
 //======================================================= reset
 // Initialize and shuffle the tiles.
 public void reset() {
	 SlidingPuzzle sp = null;
	 do {
	     for (int r=0; r<puzzleSize; r++) {
	         for (int c=0; c<puzzleSize; c++) {
	             _contents[r][c] = new Tile(r, c, "" + (r*puzzleSize+c+1));
	         }
	     }
	     //--- Set last tile face to null to mark empty space
	     _emptyTile = _contents[puzzleSize-1][puzzleSize-1];
	     _emptyTile.setFace(null);
	     
	     //-- Shuffle - Exchange each tile with random tile.
	     for (int r=0; r<puzzleSize; r++) {
	         for (int c=0; c<puzzleSize; c++) {
	             exchangeTiles(r, c, (int)(Math.random()*puzzleSize)
	                               , (int)(Math.random()*puzzleSize));
	         }
	     }
	     sp = new SlidingPuzzle(puzzleSize, _contents);
	     
	 } while (!sp.isSolvable());
     
 }//end reset
 
 
 //==================================================== moveTile
 // Move a tile to empty position beside it, if possible.
 // Return true if it was moved, false if not legal.
 public boolean moveTile(int r, int c) {
     //--- It's a legal move if the empty cell is next to it.
     return checkEmpty(r, c, -1, 0) || checkEmpty(r, c, 1, 0)
         || checkEmpty(r, c, 0, -1) || checkEmpty(r, c, 0, 1);
 }//end moveTile
 
 
 //================================================== checkEmpty
 // Check to see if there is an empty position beside tile.
 // Return true and exchange if possible, else return false.
 private boolean checkEmpty(int r, int c, int rdelta, int cdelta) {
     int rNeighbor = r + rdelta;
     int cNeighbor = c + cdelta;
     //--- Check to see if this neighbor is on board and is empty.
     if (isLegalRowCol(rNeighbor, cNeighbor) 
               && _contents[rNeighbor][cNeighbor] == _emptyTile) {
         exchangeTiles(r, c, rNeighbor, cNeighbor);
         return true;
     }
     return false;
 }//end checkEmpty
 
 
 //=============================================== isLegalRowCol
 // Check for legal row, col
 public boolean isLegalRowCol(int r, int c) {
     return r>=0 && r<puzzleSize && c>=0 && c<puzzleSize;
 }//end isLegalRowCol
 
 
 //=============================================== exchangeTiles
 // Exchange two tiles.
 public void exchangeTiles(int r1, int c1, int r2, int c2) {
     Tile temp = _contents[r1][c1];
     _contents[r1][c1] = _contents[r2][c2];
     _contents[r2][c2] = temp;
 }//end exchangeTiles
     
 
 //=================================================== isGameOver
 public boolean isGameOver() {
     for (int r=0; r<puzzleSize; r++) {
         for (int c=0; c<puzzleSize; c++) {
             Tile trc = _contents[r][c];
             return trc.isInFinalPosition(r, c);
         }
     }
     
     //--- Falling thru loop means nothing out of place.
     return true;
 }//end isGameOver
}//end class SlidePuzzleModel
 